﻿using System.Collections.Generic;
using System.Threading.Tasks;

namespace Syngine.Components
{
	public static class UpdateSyncContext
	{
		private static readonly object SyncRoot = new object();
		private static readonly List<IUpdateAsync> Updatables = new List<IUpdateAsync>();

		private static bool IsComplete { get; set; }

		public static void Add(IUpdateAsync updatable)
		{
			lock (SyncRoot)
			{
				Updatables.Add(updatable);
			}

			if (!updatable.IsInitialized)
			{
				updatable.Initialize();
			}
		}

		public static void UpdateAsync(UpdateContext context)
		{
			var tasks = new Task[Updatables.Count];

			if (tasks.Length == 0) { return; }

			lock (SyncRoot)
			{
				// Had to use Task.Factory.StartNew() instead
				// of Task.Run(), android doesn't support it.
				for (int i = 0; i < tasks.Length; i++)
				{
					tasks[i] = Task.Factory.StartNew(() => Updatables[i].UpdateAsync(context));
				}
			}

			// Had to use Task.Factory.ContinueWhenAll() instead
			// of Task.WhenAll(), android doesn't support it.
			Task.Factory.ContinueWhenAll(tasks, t =>
			{
				for (int i = 0; i < Updatables.Count; i++)
				{
					Updatables[i].Update(context);
				}

				IsComplete = true;
			});

			LoopWhileUpdatesComplete();
		}

		private static void LoopWhileUpdatesComplete()
		{
			while (!IsComplete)
			{
			}

			IsComplete = false;
		}

		public static bool Remove(IUpdateAsync updatable)
		{
			lock (SyncRoot)
			{
				return Updatables.Remove(updatable);
			}
		}
	}
}
